arc-router
A purely functional router for independently evaluating a path against a list of routes
Install
$ npm install arc-router --save
Features
Basic Usage
const ArcRouter = require('arc-router');
let Journey = new ArcRouter({
'/!wallpaper/**filePath[/]/:fileName([^\.]*\.jpg)':'wallpaper',
'/!shared/!docs/2*filePath/#docId':'doc',
'/!shared/!docs':'docsFolder'
});
const example1 = Journey.travel('/wallpaper/2016/australia/sydney/beach.jpg');
expect(example1).toEqual({
'match':'wallpaper',
'wallpaper':'wallpaper',
'filePath':'2016/australia/sydney',
'fileName': 'beach.jpg'
});
const example2 = Journey.travel('/shared/docs/important/contracts/123');
expect(example2).toEqual({
'match':'doc',
'shared':'shared',
'docs':'docs',
'filePath':['important','contracts'],
'docId': '123'
});
const example2 = Journey.travel('/shared/docs');
expect(example2).toEqual({
'match':'docsFolder',
'shared':'shared',
'docs':'docs'
});
const falseMatch = Journey.travel('/shared/docs/fail');
const falseMatch = Journey.travel('/shared/docs/import/contracts/string/123');
API
new ArcRouter([routeMap:Object])
Create a new ArcRouter
object. Requires new
, routeMap is optional in the constructor.
.setMap(routeMap:Object)
Take an object in the form of {[ROUTE]:[MATCH_NAME]} and evaluate against it
.setStripQueryParams(value:Boolean)
Sets whether or not the router should strip patterns that look like URL query params from a route being traveled. (ie ?var=1
). By default set to TRUE
.setStripAnchor(value:Boolean)
Sets whether or not the router should strip patterns that look like a URL anchor from a route being traveled (ie. #someAnchor
). By default set to TRUE
.setCaptureQuery(value:Boolean)
Sets whether or not query parameter like patterns should be captured, parsed and returned as part of the routeData object on return. By default set to FALSE
. If set to TRUE
query parameters will be appended to the routeData object as a {key:val}
object under query
.setCaptureAnchor(value:Boolean)
Sets whether or not query parameter like patterns should be captured, parsed and returned as part of the routeData object on return. By default set to FALSE
. If set to TRUE
any value after a URL #
will become the value of anchor
on the RouteData object.
.travel(routeString:String)
Accept a string to travel the route map with. Travel returns a routeData object, binding variables based on the map route patterns.
Testing
npm test
Rule Explanation
! is an explicit match - format: /!stringToMatch
Note: not case sensitive. stringToMatch is also used as keyName (boolean value)
+ is a Filter match - format: /+keyName(filterName)
Note: requires a Filter object to be added through the AddFilter method
: is a Regex match - format: /:keyName(regExPattern)
Note: regex current cannot use / anywhere in the pattern (we may handle this later on)
# is a numeric match - format: /#keyName
* is a wildcard match - format: /\*keyName
Additional modifiers:
Recursive Matching - Modifier*2
usage: !!/++/::/##/!**
Recursive states attempt to consume everything from that point until the next identifier matches.
So for example: /!wallpaper/!**filePath/:fileName([^\.]*\.jpg)
would match the following route /wallpaper/vacations/australia/goldcoast/beach.jpg
In the event of recursive or multiple matching the data is stored in an array (so routeData.filePath
would === [vacations,australia,goldcoast]
)
Multi Match - IntModifier
usage. 2* or 3+
etc
Multi states require the full number of matches to successfully match to be a match
So for example: /!file/3*namespace/!*object
would match the following /file/Ocelot/Engine/Toolbox/Router.php
Binding Modifier - [BindingPattern] (must be at end of routeChunk)
usage: [/]
This is used to bind certain parts of the route back together
So for example: /!file/3*namespace[/]/!*object
would still match the following /file/Ocelot/Engine/Toolbox/Router.php
but RouteData->namespace() would no longer be an array, instead it would be Ocelot/Engine/Toolbox
Note:
This code was based upon ancient code, which was based upon ancient code, continually tweaked as we used it for more. It works fairly well but has some assumed bugs
Bug2: / in anything will pretty much fail. While we built a special case for the binding parameter, we still use it to split which will result in obvious failure
These bugs are all pretty fixable.
/
will continue to be what we split with but for regEx we could tokenize the regex the same we tokenize the binding, and then reassign